/* Copyright (c) 2004-2024 Peigen.info. All rights reserved. */

package info.peigen.hotpot.business.customer.core.domain;

import com.google.common.collect.Lists;
import info.peigen.hotpot.business.account.core.domain.account.Account;
import info.peigen.hotpot.business.account.core.util.CreateAccountUtil;
import info.peigen.hotpot.business.customer.core.domain.action.CustomerDomainAction;
import info.peigen.hotpot.business.customer.core.domain.auth.CustomerAuthentication;
import info.peigen.hotpot.business.customer.core.domain.operator.CustomerOperator;
import info.peigen.hotpot.business.customer.core.domain.partner.Partner;
import info.peigen.hotpot.business.customer.core.domain.weixin.miniapp.WxMiniappUser;
import info.peigen.hotpot.business.customer.facade.enums.CustomerAction;
import info.peigen.hotpot.business.customer.facade.enums.CustomerSource;
import info.peigen.hotpot.business.customer.facade.enums.CustomerStatus;
import info.peigen.hotpot.business.customer.facade.order.register.CustomerRegisterOrder;
import info.peigen.hotpot.business.customer.facade.order.weixin.miniapp.CustomerWxMiniappLoginOrder;
import info.peigen.hotpot.common.core.domain.Domain;
import info.peigen.hotpot.common.core.domain.DomainObject;
import info.peigen.hotpot.common.core.order.Order;
import info.peigen.hotpot.common.core.util.IdUtil;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.FieldDefaults;
import lombok.experimental.SuperBuilder;
import org.beetl.sql.annotation.entity.ResultProvider;
import org.beetl.sql.core.mapping.join.AutoJsonMapper;

import java.util.List;
import java.util.Optional;

import static info.peigen.hotpot.business.customer.facade.enums.CustomerStatus.Init;
import static info.peigen.hotpot.business.customer.facade.enums.CustomerStatus.Un_Cert;
import static info.peigen.hotpot.business.customer.facade.enums.operator.CustomerOperatorStatus.Enable;

/**
 * <b>(Customer)</b>
 * 客户领域对象
 *
 * @author Peigen
 * @version 1.0.0
 * @since 2021/7/27
 */
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
@Accessors(chain = true)
@ResultProvider(AutoJsonMapper.class)
public class Customer extends DomainObject {
    /** 客户Id,有别于表id */
    @Size(max = 24)
    @Builder.Default
    String         customerId = IdUtil.id();
    /** 客户状态 */
    @NotNull
    @Builder.Default
    CustomerStatus status     = Init;
    /** 客户基础信息 */
    CustomerBase           customerBase;
    /** 实名认证 */
    CustomerAuthentication authentication;
    /** 主操作员 */
    CustomerOperator       masterOperator;
    /** 所有操作员 ？ */
    List<CustomerOperator> operators;
    /** 客户权限 ？ */
    CustomerPermission     permission;
    /** 客户账户 */
    Account                account;
    /** 客户营销相关信息 */
    CustomerMarketing      customerMarketing;
    /** 客户技术相关信息 */
    CustomerTech           customerTech;
    /** 收费规则 */
    CustomerFeeRule        customerFeeRule;
    /** 客户等级 */
    CustomerLevel          level;
    /** 客户来源 */
    @Builder.Default
    CustomerSource source = CustomerSource.Weixin;

    @Override
    public Domain create(Order order) {
        if (order instanceof CustomerRegisterOrder) {
            return createCustomer((CustomerRegisterOrder) order);
        } else if (order instanceof CustomerWxMiniappLoginOrder) {
            CustomerWxMiniappLoginOrder miniappLoginOrder = (CustomerWxMiniappLoginOrder) order;
            CustomerRegisterOrder registerOrder = CustomerRegisterOrder.builder()
                    .partnerId(miniappLoginOrder.getPartnerId())
                    .source(miniappLoginOrder.getSource())
                    .build();
            Customer customer = createCustomer(registerOrder);
            customer.getCustomerTech().getWxMiniappUser().setLoginCode(miniappLoginOrder.getCode())
                    .setSessionKey(miniappLoginOrder.getSessionKey())
                    .setOpenid(miniappLoginOrder.getOpenid());
            return customer;
        }
        return null;
    }

    private Customer createCustomer(CustomerRegisterOrder order) {
        Customer customer = init();

        // 设置注册来源
        customer.setSource(order.getSource());

        // 设置Operator状态
        customer.getMasterOperator().setStatus(Enable)
                .setLoginName(order.getLoginName())
                .setLoginPassword(order.getLoginPassword());
        customer.setOperators(Lists.newArrayList(customer.getMasterOperator()));

        // 设置partnerId
        customer.setPartnerId(Optional.ofNullable(order.getPartnerId()).orElse(Partner.ReArchCN_PartnerId));

        // 设置Customer状态
        customer.setStatus(Un_Cert);

        return customer;
    }

    public Domain action(Order order, CustomerAction action) {
        switch (action) {
            case login:
                CustomerDomainAction.login(this, order);
                break;
            case freeze:
                CustomerDomainAction.freeze(this, order);
                break;
            case delete:
                CustomerDomainAction.delete(this, order);
                break;
            case applyAuthentication:
                CustomerDomainAction.applyAuthentication(this, order);
                break;
            case auditAuthentication:
                CustomerDomainAction.auditAuthentication(this, order);
                break;
            default:
                return this;
        }
        return this;
    }

    protected Customer init() {
        String customerId = CreateAccountUtil.createCustomerAccountId();
        return Customer.builder().customerId(customerId)
                .level(CustomerLevel.builder().build())
                .permission(CustomerPermission.builder().build())
                .customerBase(CustomerBase.builder().build())
                .masterOperator(CustomerOperator.builder().operatorId(customerId).build())
                .customerTech(CustomerTech.builder().wxMiniappUser(WxMiniappUser.builder().build()).build())
                .build();
    }
}